// G4提供的头文件
#include "G4Box.hh"                 // G4的长方体几何体
#include "G4Orb.hh"                 // G4的球形几何体
#include "G4Tubs.hh"                // G4的圆柱体
#include "G4LogicalVolume.hh"       // G4的逻辑体
#include "G4PVPlacement.hh"         // G4的物理实体摆放器
#include "G4SystemOfUnits.hh"       // G4系统单位制
#include "G4NistManager.hh"         // G4材料查找表
#include "G4Material.hh"            // G4材料
#include "G4VisAttributes.hh"       // G4逻辑体外观管理器
#include "G4Color.hh"               // G4的颜色
// 用户编写的头文件
#include "G4BasicDetectorConstruction.hh"

// G4物理建模函数
G4VPhysicalVolume * G4BasicDetectorConstruction::Construct(){

    // 创建材料查找表
    auto nistManager = G4NistManager::Instance();

    // 检查边界冲突的变量控制
    G4bool checkOverlaps = true;

    /***********************创建一种新材料**********************************/
    // 创建化合物————酒精(C2H5OH)
    G4double density = 0.800*g/cm3;     // 定义酒精密度

    G4Material* myG4Alcohol = new G4Material("Alcohol", // 名称
                                             density,   // 密度
                                             3);        // 构成元素种类
    myG4Alcohol->AddElement(nistManager->FindOrBuildElement("C"),2);    // 将C元素添加到创建的材料中，原子量为2
    myG4Alcohol->AddElement(nistManager->FindOrBuildElement("H"),6);    // 将H元素添加的创建的材料中，原子量为6
    myG4Alcohol->AddElement(nistManager->FindOrBuildElement("O"),1);    // 将O元素添加带创建的材料中，原子量为1

    // 创建混合物————二锅头
    G4Material* myWine = new G4Material("Wine",         // 名称
                                          0.7*g/cm3,    // 密度
                                          2);           // 组成物质种类
    myWine->AddMaterial(nistManager->FindOrBuildMaterial("G4_WATER"),48*perCent);   // 水占48%
    myWine->AddMaterial(myG4Alcohol,52*perCent);                                    // 酒精占52%

    /***********************创建G4 World**********************************/
    // 创建World几何体
    auto * solid_world = new G4Box("world",
                                    2*m,
                                    2*m,
                                    2*m);
    // 创建World逻辑体
    auto * logic_world = new G4LogicalVolume(solid_world,           
                                             nistManager->FindOrBuildMaterial("G4_AIR"),
                                             "world");
    // 创建world物理体
    auto * physical_world = new G4PVPlacement(0,
                                              G4ThreeVector(0,0,0),
                                              logic_world,
                                              "world",
                                              0,
                                              false,
                                              0,
                                              checkOverlaps);
    
    /***********************肌肉小球**********************************/
    // 创建肌肉小球几何体
    auto * solid_muscle = new G4Orb("muscle",
                                    10*cm);
    // 创建肌肉小球逻辑体
    auto * logic_muscle = new G4LogicalVolume(solid_muscle,
                                              nistManager->FindOrBuildMaterial("G4_MUSCLE_SKELETAL_ICRP"),
                                              "muscle");
    // 配置肌肉小球外观
    auto visAttributs_musle = new G4VisAttributes(G4Color::Red());      // 颜色为红色
    visAttributs_musle->SetVisibility(true);                            // 打开外观显示
    visAttributs_musle->SetForceSolid(true);                            // 外观设置为实心全填充
    logic_muscle->SetVisAttributes(visAttributs_musle);                 // 外观信息配置到logic_muscle


    // 创建肌肉小球物理体(使用for循环摆放两个)
    for(G4int i=1;i<=2;i++){
        auto * physical_nuscle = new G4PVPlacement(0,
                                                   G4ThreeVector((50*i)*cm,0,0),
                                                   logic_muscle,
                                                   "muscle",
                                                   logic_world,
                                                   false,
                                                   1,
                                                   checkOverlaps);
    }
    
    
    /***********************二锅头小柱**********************************/
    // 创建二锅头小柱几何体
    auto * solid_wine = new G4Tubs("wine",      // 几何柱体名
                                    0*cm,       // 内径
                                    20*cm,      // 外径
                                    25*cm,      // 柱体的半高
                                    0*deg,      // 起始角度
                                    360*deg);   // 扇形扫掠的角度，这里设置为 360 度表示完整的圆形
    // 创建二锅头小柱逻辑体
    auto * logic_wine = new G4LogicalVolume(solid_wine,     // 待填充的几何体
                                            myWine,         // 填充材料
                                            "wine");        // 逻辑体名

    // 配置二锅头小柱外观
    auto * visAttributs_wine = new G4VisAttributes(G4Color::White());   // 颜色为红色
    visAttributs_wine->SetVisibility(true);                             // 打开外观显示
    visAttributs_wine->SetForceSolid(true);                             // 外观设置为实心全填充
    logic_wine->SetVisAttributes(visAttributs_wine);                    // 外观信息配置到logic_wine

    // 创建二锅头小柱物理体
    auto * physical_wine = new G4PVPlacement(0,                             // 是否旋转
                                             G4ThreeVector(0,60*cm,0),      // 摆放位置
                                             logic_wine,                    // 待摆放的逻辑体
                                             "wine",                        // 物理实体名
                                             logic_world,                   // 母体
                                             false,                         // 不镜像
                                             2,                             // 物理实体编号
                                             checkOverlaps);                // 打开边界冲突检查

    // 设置敏感体积
    fScoringVolume = logic_wine;        // 将敏感体积设置为logic_wine

    // 返回世界
    return physical_world;              // 将整个world交给runmanager

}

// 用于其他类获取设置的敏感体积的成员函数
G4LogicalVolume* G4BasicDetectorConstruction::GetScoringVolume() const{

    // 外部类获取敏感体积的函数
    return fScoringVolume;

}